/**
 * 
 */
package org.mspring.mlog.service.impl;

import java.util.Date;
import java.util.List;

import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.mspring.mlog.entity.Attachment;
import org.mspring.mlog.entity.Comment;
import org.mspring.mlog.entity.Post;
import org.mspring.mlog.service.AttachmentService;
import org.mspring.mlog.service.PostCatalogService;
import org.mspring.mlog.service.PostService;
import org.mspring.mlog.web.security.SecurityUtils;
import org.mspring.platform.cache.service.DefaultCacheService;
import org.mspring.platform.dao.hibernate.GenericDao;
import org.mspring.platform.dao.hibernate.common.EnhancedRule;
import org.mspring.platform.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author Gao Youbo
 * @since 2012-7-18
 * @Description
 * @TODO
 */
@Service
@Transactional
public class PostServiceImpl extends GenericDao<Post, java.lang.Long> implements PostService {

    @Autowired
    private PostCatalogService catalogService;

    @Autowired
    private AttachmentService attachmentService;

    @Autowired
    private DefaultCacheService defaultCacheService;

    @Override
    public Post save(Post post) {
        // TODO Auto-generated method stub
        if (post.getCreateTime() == null) {
            post.setCreateTime(new Date());
        }
        if (StringUtils.isBlank(post.getCommentStatus())) {
            post.setCommentStatus(Post.CommentStatus.OPEN);
        }
        if (StringUtils.isBlank(post.getStatus())) {
            post.setStatus(Post.Status.PUBLISH);
        }
        if (post.getIsTop() == null) {
            post.setIsTop(false);
        }
        if (post.getAuthor() == null) {
            post.setAuthor(SecurityUtils.getCurrentUser());
        }
        return super.save(post);
    }

    @Override
    public Post merge(Post post) {
        // TODO Auto-generated method stub
        if (post.getCreateTime() == null) {
            post.setCreateTime(new Date());
        }
        if (StringUtils.isBlank(post.getCommentStatus())) {
            post.setCommentStatus(Post.CommentStatus.OPEN);
        }
        if (StringUtils.isBlank(post.getStatus())) {
            post.setStatus(Post.Status.PUBLISH);
        }
        if (post.getIsTop() == null) {
            post.setIsTop(false);
        }
        if (post.getAuthor() == null) {
            post.setAuthor(SecurityUtils.getCurrentUser());
        }
        return super.merge(post);
    }

    @Override
    public void discardPost(Long... idArray) {
        // TODO Auto-generated method stub
        for (Long id : idArray) {
            String hql = "update Post post set post.status = ? where post.id = ?";
            executeUpdate(hql, new Object[] { Post.Status.TRASH, id });
        }
    }

    @Override
    public void trash2Publish(Long... idArray) {
        // TODO Auto-generated method stub
        for (Long id : idArray) {
            String hql = "update Post post set post.status = ? where post.id = ? and post.status = ?";
            executeUpdate(hql, new Object[] { Post.Status.PUBLISH, id, Post.Status.TRASH });
        }
    }

    @Override
    public void updatePost(Post post) {
        // TODO Auto-generated method stub
        post.setModifyTime(new Date());
        if (post.getCreateTime() == null) {
            post.setCreateTime(new Date());
        }
        if (StringUtils.isBlank(post.getCommentStatus())) {
            post.setCommentStatus(Post.CommentStatus.OPEN);
        }
        if (StringUtils.isBlank(post.getStatus())) {
            post.setStatus(Post.Status.PUBLISH);
        }
        if (post.getIsTop() == null) {
            post.setIsTop(false);
        }
        update(post);
    }

    @Override
    public List<Post> recent(int nums) {
        // TODO Auto-generated method stub
        EnhancedRule rule = new EnhancedRule();
        rule.add(Restrictions.eq("status", Post.Status.PUBLISH));
        rule.addOrder(Order.desc("createTime"));
        rule.setPageSize(nums);
        return list(rule);
    }

    @Override
    public List<Post> recent(Long user, int nums) {
        // TODO Auto-generated method stub
        if (user == null) {
            return null;
        }
        EnhancedRule rule = new EnhancedRule();
        rule.add(Restrictions.eq("author.id", user));
        rule.add(Restrictions.eq("status", Post.Status.PUBLISH));
        rule.addOrder(Order.desc("createTime"));
        rule.setPageSize(nums);
        return list(rule);
    }

    @Override
    public List<Post> recent(Long user, Long catalog, int nums, Date start, Date end) {
        // TODO Auto-generated method stub
        if (user == null) {
            return null;
        }
        if (catalog != null) {
            EnhancedRule rule = new EnhancedRule();
            if (start != null) {
                rule.add(Restrictions.ge("createTime", start));
            }
            if (end != null) {
                rule.add(Restrictions.le("createTime", end));
            }
            rule.add(Restrictions.eq("author.id", user));
            rule.add(Restrictions.eq("status", Post.Status.PUBLISH));
            rule.add(Restrictions.eq("catalog.id", catalog));
            rule.addOrder(Order.desc("createTime"));
            rule.setPageSize(nums);
            return list(rule);
        }
        return null;
    }

    @Override
    public List<Post> hot(int nums, Date start, Date end) {
        // TODO Auto-generated method stub
        EnhancedRule rule = new EnhancedRule();
        if (start != null) {
            rule.add(Restrictions.ge("createTime", start));
        }
        if (end != null) {
            rule.add(Restrictions.le("createTime", end));
        }
        rule.add(Restrictions.eq("status", Post.Status.PUBLISH));
        rule.addOrder(Order.desc("views"));
        rule.setPageSize(nums);
        return list(rule);
    }

    @Override
    public List<Post> hot(Long user, int nums, Date start, Date end) {
        // TODO Auto-generated method stub
        if (user == null) {
            return null;
        }
        EnhancedRule rule = new EnhancedRule();
        if (start != null) {
            rule.add(Restrictions.ge("createTime", start));
        }
        if (end != null) {
            rule.add(Restrictions.le("createTime", end));
        }
        rule.add(Restrictions.eq("author.id", user));
        rule.add(Restrictions.eq("status", Post.Status.PUBLISH));
        rule.addOrder(Order.desc("views"));
        rule.setPageSize(nums);
        return list(rule);
    }

    @Override
    public List<Post> hot(Long user, Long catalog, int nums, Date start, Date end) {
        // TODO Auto-generated method stub
        if (user == null) {
            return null;
        }
        if (catalog != null) {
            EnhancedRule rule = new EnhancedRule();
            if (start != null) {
                rule.add(Restrictions.ge("createTime", start));
            }
            if (end != null) {
                rule.add(Restrictions.le("createTime", end));
            }
            rule.add(Restrictions.eq("author.id", user));
            rule.add(Restrictions.eq("status", Post.Status.PUBLISH));
            rule.add(Restrictions.eq("catalog.id", catalog));
            rule.addOrder(Order.desc("views"));
            rule.setPageSize(nums);
            return list(rule);
        }
        return null;
    }

    @Override
    public List<Post> top(Long user, int nums) {
        // TODO Auto-generated method stub
        if (user == null) {
            return null;
        }
        EnhancedRule rule = new EnhancedRule();
        rule.add(Restrictions.eq("isTop", true));
        rule.add(Restrictions.eq("author.id", user));
        rule.add(Restrictions.eq("status", Post.Status.PUBLISH));
        rule.addOrder(Order.desc("id"));
        rule.setPageSize(nums);
        return list(rule);
    }

    @Override
    public void updatePostComments(Long postId) {
        // TODO Auto-generated method stub
        if (postId != null) {
            executeUpdate("update Post set comments = (select count(*) from Comment comment where comment.status = ? and comment.post.id = ?) where id = ?", new Object[] { Comment.Status.APPROVED, postId, postId });
        }
    }

    @Override
    public String getPostUrlByCommentId(Long commentId) {
        // TODO Auto-generated method stub
        String queryString = "select post.url from Post post, Comment comment where comment.post.id = post.id and comment.id = ?";
        Object url = getHibernateTemplate().uniqueResult(queryString, commentId);
        return url == null ? "" : url.toString();
    }

    @Override
    public Post getPostByComment(Long commentId) {
        // TODO Auto-generated method stub
        String queryString = "select post from Post post, Comment comment where comment.post.id = post.id and comment.id = ?";
        return uniqueResult(queryString, commentId);
    }

    @Override
    public void clearTrash() {
        // TODO Auto-generated method stub
        String hql = "delete Post post where post.status = ?";
        executeUpdate(hql, Post.Status.TRASH);
    }

    @Override
    public boolean hasPermisstion(Long postId, String password) {
        // TODO Auto-generated method stub
        Post post = get(postId);
        if (StringUtils.isBlank(post.getPassword())) {
            return true;
        } else if (post.getPassword().equals(password)) {
            return true;
        }
        return false;
    }

    @Override
    public void movePostCatalog(Long fromCatalog, Long toCatalog) {
        // TODO Auto-generated method stub

    }

    @Override
    public void setPostTop(Long id, boolean top) {
        // TODO Auto-generated method stub
        if (id == null) {
            return;
        }
        executeUpdate("update Post post set post.isTop = ? where post.id = ?", new Object[] { top, id });
    }

    @Override
    public void remove(Post object) {
        // TODO Auto-generated method stub
        if (object == null || object.getId() == null) {
            return;
        }
        remove(object.getId());
    }

    @Override
    public void remove(Long... ids) {
        // TODO Auto-generated method stub
        for (Long id : ids) {
            if (id == null) {
                return;
            }
            List<Attachment> attachments = attachmentService.findAttachments(id.toString(), Attachment.AttachFromType.FROM_NEWS);
            for (Attachment attachment : attachments) {
                attachmentService.deleteAttachment(attachment.getId());
            }
            super.remove(id);
        }
    }

    @Override
    public void safeRemove(Long id, Long user) {
        // TODO Auto-generated method stub
        if (user == null || id == null) {
            return;
        }
        executeUpdate("delete from Post post where post.id = ? and post.author.id = ?", id, user);
    }

    @Override
    public Long getViews(Long id) {
        // TODO Auto-generated method stub
        Object views = uniqueResult("select post.views from Post post where post.id = ?", id);
        if (views == null || StringUtils.isBlank(views.toString())) {
            return Long.valueOf(0);
        }
        return Long.valueOf(views.toString().trim());
    }
}
